package com.hualude.roadsign.utils;

import com.hualude.roadsign.dto.UserDto;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by SN on 2017/2/25.
 */
@Aspect
@Component
public class LoggingAspect {

    private static Logger logger = Logger.getLogger(LoggingAspect.class);

    /**
     * 声明切入点表达式，一般在该方法中不再添加其他代码。
     * 使用@Pointcut来声明切入点表达式。
     * 后面的通知直接使用方法名来引用当前的切入点表达式。
     */
    @Pointcut("execution(* com.hualude.roadsign.service.impl.*.add*(..))||execution(* com.hualude.roadsign.service.impl.*.update*(..))||execution(* com.hualude.roadsign.service.impl.*.delete*(..))")
    public void declareJoinPointExpression() {
    }

    /**
     * 前置通知，在目标方法开始之前执行。
     *
     * @param joinpoint
     */
    @Before("declareJoinPointExpression()")
    // 这里使用切入点表达式即可。后面的可以都改成切入点表达式。如果这个切入点表达式在别的包中，在前面加上包名和类名即可。
    public void beforeMethod(JoinPoint joinpoint) {
    }

    /**
     * 后置通知，在目标方法执行之后开始执行，无论目标方法是否抛出异常。
     * 在后置通知中不能访问目标方法执行的结果。
     *
     * @param joinpoint
     */
    @After("declareJoinPointExpression()")
    public void afterMethod(JoinPoint joinpoint) {
    }

    /**
     * 返回通知，在方法正常结束之后执行。
     * 可以访问到方法的返回值。
     *
     * @param joinpoint
     * @param result    目标方法的返回值
     */
    @AfterReturning(value = "declareJoinPointExpression()", returning = "result")
    public void afterReturnning(JoinPoint joinpoint, Object result) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpSession labTeacherLoginSession = request.getSession();
        UserDto userDto = (UserDto) labTeacherLoginSession.getAttribute("rdsUserLoginSession");
        String strLogger = "操作日志：方法名：" + joinpoint.getSignature().getName() + "，返回值：" + result;
        if(userDto != null)
        strLogger += "，操作人：" + userDto.getUserId() + "-" + userDto.getLoginName() + "-" + userDto.getUserName();
        strLogger += "，时间：" + df.format(new Date());
        logger.info(strLogger);
    }

    /**
     * 异常通知。目标方法出现异常的时候执行，可以访问到异常对象，可以指定在出现特定异常时才执行。
     * 假如把参数写成NullPointerException则只在出现空指针异常的时候执行。
     *
     * @param joinpoint
     * @param e
     */
    @AfterThrowing(value = "declareJoinPointExpression()", throwing = "e")
    public void afterThrowing(JoinPoint joinpoint, Exception e) {
    }
}
